package com.ecode.ecny.flow;

import com.ecode.ecny.base.AppContext;
import com.ecode.ecny.base.ReqHead;
import com.ecode.ecny.base.TxnStatus;
import com.ecode.ecny.exception.TrxErrorEnums;
import com.ecode.ecny.exception.TrxException;
import com.ecode.ecny.mobel.InspectDo;
import com.ecode.ecny.service.TrxFlowService;
import com.ecode.ecny.dao.InspectMapper;
import com.ecode.ecny.dto.BaseReqDTO;
import com.ecode.ecny.dto.BaseRspDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @ClassName FlowExcutor
 * @Author mjlft
 * @Date 2021/8/14 14:13
 * @Version 1.0
 * @Description 流程执行器
 */
@Component
public class FlowExecutor implements ApplicationContextAware {

    private Logger logger = LoggerFactory.getLogger(FlowExecutor.class);

    private ApplicationContext applicationContext;

    @Autowired
    private InspectMapper inspectMapper;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public BaseRspDTO execute(String flowName, BaseReqDTO<?> reqDTO) {
        //堵重
        validRepeat(reqDTO);

        FlowContent flowContent = FlowContent.createInstance(reqDTO);

        //做交易
        //获取执行流程
        TrxFlowService trxFlowService = applicationContext.getBean(flowName, TrxFlowService.class);
        trxFlowService.doFlow(flowContent);

        //错误处理
        return flowContent.getRspDTO();
    }

    /**
     * 交易堵重
     *
     * @param reqDTO
     */
    public void validRepeat(BaseReqDTO<?> reqDTO) {
        ReqHead head = reqDTO.getHead();
        try {
            InspectDo inspectDo = InspectDo.createInstance(head, AppContext.DIRECT_SEND, null);
            int res = inspectMapper.inspect(inspectDo);
            if (res != 1) {
                throw new TrxException(TrxErrorEnums.SYS_INSPECT_REP, TxnStatus.FAIL);
            }
        } catch (TrxException ex) {
            logger.info("交易【{}】重复", head.getReqNo(), ex);
            throw ex;
        } catch (Exception e) {
            logger.info("交易【{}】重复", head.getReqNo(), e);
            throw new TrxException(TrxErrorEnums.SYS_INSPECT_REP, TxnStatus.FAIL);
        }
    }
}
